#ifndef _CU_FLOAT1_H_
#define _CU_FLOAT1_H_
//**********************************************************************************
// float1 operators and functions
//**********************************************************************************

SDH_CALL uint32 as_uint(float   f) { return *((uint32 *) &f );}
SDH_CALL float  as_float(uint32 ui) { return *((float  *) &ui);}


SDH_CALL int32  as_int (float   f) { return *((int32  *) &f );}
SDH_CALL float  as_float (int32   i) { return *((float  *) &i );}

SDH_CALL float1 operator + (const float1 & u, float v) { float1 r = { u.x + v }; return r; }
SDH_CALL float1 operator - (const float1 & u, float v) { float1 r = { u.x - v }; return r; }
SDH_CALL float1 operator * (const float1 & u, float v) { float1 r = { u.x * v }; return r; }
SDH_CALL float1 operator / (const float1 & u, float v) { float1 r = { u.x / v }; return r; }

SDH_CALL float1 operator + (float v, const float1 & u) { float1 r = { v + u.x }; return r; }
SDH_CALL float1 operator - (float v, const float1 & u) { float1 r = { v - u.x }; return r; }
SDH_CALL float1 operator * (float v, const float1 & u) { float1 r = { v * u.x }; return r; }
SDH_CALL float1 operator / (float v, const float1 & u) { float1 r = { v / u.x }; return r; }

SDH_CALL float1 operator + (const float1 & u, const float1 & v) { float1 r = { u.x + v.x }; return r; }
SDH_CALL float1 operator - (const float1 & u, const float1 & v) { float1 r = { u.x - v.x }; return r; }
SDH_CALL float1 operator * (const float1 & u, const float1 & v) { float1 r = { u.x * v.x }; return r; }
SDH_CALL float1 operator / (const float1 & u, const float1 & v) { float1 r = { u.x / v.x }; return r; }

SDH_CALL float1   operator - (const float1 & v) { float1 r = { -v.x }; return r; }

SDH_CALL float1 & operator += (float1 & u, const float1 & v) { u.x += v.x; return u; }
SDH_CALL float1 & operator -= (float1 & u, const float1 & v) { u.x -= v.x; return u; }
SDH_CALL float1 & operator *= (float1 & u, const float1 & v) { u.x *= v.x; return u; }
SDH_CALL float1 & operator /= (float1 & u, const float1 & v) { u.x /= v.x; return u; }

SDH_CALL float1 & operator += (float1 & u, float v) { u.x += v; return u; }
SDH_CALL float1 & operator -= (float1 & u, float v) { u.x -= v; return u; }
SDH_CALL float1 & operator *= (float1 & u, float v) { u.x *= v; return u; }
SDH_CALL float1 & operator /= (float1 & u, float v) { u.x /= v; return u; }

SDH_CALL float1 catmullrom (const float1 & P0, const float1 & P1, const float1 & P2, const float1 & P3, float t)
{
  const float ts = t * t;
  const float tc = t * ts;

  return (P0 * (-tc + 2.0f * ts - t) + P1 * (3.0f * tc - 5.0f * ts + 2.0f) + P2 * (-3.0f * tc + 4.0f * ts + t) + P3 * ( tc - ts)) * 0.5f;
}
SDH_CALL float1 lerp      (const float1 & u, const float1 & v, float t ) { return u + t * (v - u); }
SDH_CALL float  dot       (const float1 & u, const float1 & v) { return (u.x*v.x); }
SDH_CALL float1 clamp     (const float1 & u, float a, float b) { float1 r = { clamp(u.x, a, b) }; return r; }

SDH_CALL float1 saturate  (const float1 & u) { return clamp(u, 0.0f, 1.0f); }

SDH_CALL float1 min(const float1 & u, const float1 & v){ float1 r = {min(u.x, v.x)}; return r; }
SDH_CALL float1 max(const float1 & u, const float1 & v){ float1 r = {max(u.x, v.x)}; return r; }

SDH_CALL float  sad (const float1 & u, const float1 & v) { return (abs(u.x - v.x)); } // Sum of Absolute Differences for x components
SDH_CALL float  ssd (const float1 & u, const float1 & v) { return (sqr(u.x - v.x)); } // Sum of Squared Differences for x components

SDH_CALL float1 f1(float x){ float1 v = {x}; return v;}

SDH_CALL uchar4 to_uchar4(const float1 & u) { uchar4 r = {u.x*255.0f, u.x*255.0f, u.x*255.0f, u.x*255.0f }; return r; }
SDH_CALL uchar1 to_uchar1(const float1 & u) { uchar1 r = {u.x*255.0f}; return r; }

SDH_CALL float  length    (const float1 & u) { return abs(u.x); }
SDH_CALL float1 normalize (const float1 & u) { float1 v = {1.0f}; return v;}

#endif